﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Dominio;
using System.Data.Objects;
using Excepciones;

namespace Servicios
{
    public class UsuarioServiceDataBaseImpl : GenericService<Usuario>, IUsuarioService, IUsuarioClienteService
    {

        private ILogService logService = FabricaDeServicios.ObtenerInstancia().ObtenerLogService();

        private static UsuarioServiceDataBaseImpl instancia = new UsuarioServiceDataBaseImpl();

        private UsuarioServiceDataBaseImpl() : base() { }

        public static UsuarioServiceDataBaseImpl ObtenerInstancia()
        {
            return instancia;
        }

        public override void Registrar(Usuario t)
        {

            Usuario usuario = this.ObtenerUsuarioPorUserName(t.NombreUsuario);
            using (Ctx)
            {
                if (usuario != null)
                {
                    throw new DataBaseException("Ya existe un usario con el nombre " + t.Nombre + " en la base de datos");
                }
                //t.Password = ClaseUtilitaria.Encriptar(t.Password);
                base.Registrar(t);
            }
        }
        
        public bool ValidarUsuario(string nombreUsuario, string password)
        {
            using (DominioContainer ctx = new DominioContainer())
            {
                try
                {
                    string encryptedPass = ClaseUtilitaria.Encriptar(password);
                    Usuario usu = ctx.Usuarios.First(u => u.NombreUsuario == nombreUsuario && u.Password == encryptedPass);//password);
                    if (usu != null)
                    {
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
            return false;
        }

        public bool ValidarUsuarioCliente(string nombreUsuario, string password)
        {
            using (DominioContainer ctx = new DominioContainer())
            {
                var query = from usu in ctx.Usuarios
                            where usu.NombreUsuario == nombreUsuario
                            select usu.Rol;

                foreach (var rol in query)
                {
                    if (!RolEnum.VISITANTE.Equals((RolEnum)Enum.Parse(typeof(RolEnum), rol.Id.ToString()))) 
                    {
                        return ValidarUsuario(nombreUsuario, password);
                    }
                }
                return false;
            }
        }

        protected override ObjectSet<Usuario> GetObjectSet(DominioContainer ctx)
        {
            return ctx.Usuarios;
        }


        public void Modificar(Usuario usuario)
        {
            using (DominioContainer ctx = new DominioContainer())
            {
                Usuario usu = null;
                try
                {
                    usu = ctx.Usuarios.First(u => u.Id == usuario.Id);
                }
                catch (Exception ex)
                {
                    throw new DataBaseException("Usuario no existente en la base de datos.");
                }
                if (usu == null)
                {
                    throw new DataBaseException("No existe un usuario con id " + usuario.Id + " en la base de datos.");
                }
                if (!usu.Password.Equals(usuario.Password)) {
                    //si pasa esto es que estamos modificando el password
                    usu.Password = ClaseUtilitaria.Encriptar(usuario.Password);
                }
                
                usu.Nombre = usuario.Nombre;
                usu.Apellido = usuario.Apellido;
                usu.NombreUsuario = usuario.NombreUsuario;
                usu.Email = usuario.Email;
                usu.RolId = usuario.RolId;
                
                ctx.SaveChanges();
            }
        }

        public Usuario ObtenerUsuarioPorUserName(string userName)
        {
            using (DominioContainer ctx = new DominioContainer())
            {
                try
                {
                    Usuario usuario = ctx.Usuarios.First(u => u.NombreUsuario == userName);
                    var query = from u in ctx.Usuarios
                                where u.Id == usuario.Id
                                select u.Rol;

                    foreach (Rol r in query) //es solo 1
                    {
                        usuario.Rol = r;
                    }
                    return usuario;
                }
                catch (Exception ex)
                {
                    return null;
                }

            }
        }

        public Usuario ObtenerPorId(int id)
        {
            using (DominioContainer ctx = new DominioContainer())
            {
                try
                {
                    Usuario usuario = ctx.Usuarios.First(u => u.Id == id);
                    return usuario;
                }
                catch (Exception ex)
                {
                    return null;
                }
            }
        }


        public List<Usuario> ObtenerUsuariosPorRol(Rol rol)
        {
            using (DominioContainer ctx = new DominioContainer())
            {
                List<Usuario> usuarios = new List<Usuario>();
                var query = from usu in ctx.Usuarios
                            where usu.Rol.Id == rol.Id
                            select usu;

                foreach (var usu in query)
                {
                    usuarios.Add(usu);   
                }
                return usuarios;
            }
        }
    }
}
